package com.ldn.server.mqtt.covert;

import com.ldn.common.basic.utils.system.StrUtils;
import com.ldn.server.mqtt.config.CovertType;
import jakarta.annotation.PostConstruct;
import jakarta.annotation.Resource;
import lombok.extern.slf4j.Slf4j;
import org.dromara.mica.mqtt.codec.MqttPublishMessage;
import org.dromara.mica.mqtt.codec.MqttQoS;
import org.springframework.scheduling.annotation.Async;
import org.springframework.stereotype.Component;
import org.tio.core.ChannelContext;

/**
 * @author 李大牛家的牛 (scafel@163.com)
 * @product serverless
 * @className MqttCovert
 * @createDate 2025/2/25 - 13:14
 * @description ToDo...
 **/
@Slf4j
@Component
public class MqttCovert {

    @Resource
    private MemberCovert memberCovert;

    // 维护一个本类的静态变量 方便使用相关注入属性
    private static MqttCovert covert;

    @PostConstruct
    public void init() {
        covert = this;
    }

    /**
     * Mqtt账号密码认证
     * @param uniqueId 设别id
     * @param userName 账号
     * @param password 密码
     * @return true/false true 认证成功 false 认证失败
     */
    public boolean checkAuthenticate(String uniqueId, String userName, String password) {
        log.info("checkAuthenticate :uniqueId => {}" , uniqueId);
        CovertType covertType = covert.checkMqttClient(uniqueId, userName, password);
        if (covertType == null) {
            return false;
        }
        return covertType.checkAuthenticate(uniqueId, userName, password);
    }

    /**
     * Mqtt订阅主题验证
     * @param clientId 设别id
     * @param topicFilter 订阅主题
     * @return true/false true 认证成功 false 认证失败
     */
    public boolean checkCanSubTopic(String clientId, String topicFilter) {
        CovertType covertType = covert.checkMqttClient(clientId);
        if (covertType == null) {
            return false;
        }
        return covertType.checkCanSubTopic(clientId, topicFilter);
    }

    /**
     * Mqtt消息处理
     * @param context Mqtt消息上下文
     * @param clientId 客户端唯一Id
     * @param topic 订阅主题
     * @param qoS QoS等级
     * @param message 发送的消息
     */
    @Async
    public void messageHandler(ChannelContext context, String clientId, String topic, MqttQoS qoS, MqttPublishMessage message) {
        log.info("messageHandler :context => {}" , context);
        log.info("messageHandler :clientId => {}" , clientId);
        log.info("messageHandler :topic => {}" , topic);
        log.info("messageHandler :qoS => {}" , qoS);
        log.info("messageHandler :message => {}" , message);
        CovertType covertType = covert.checkMqttClient(clientId);
        if (covertType == null) {
            log.error("异常的消息接收clientId => {}", clientId);
            return;
        }
        covertType.messageHandler(context, clientId, topic, qoS, message);
    }

    /**
     * Mqtt上线处理
     * @param context Mqtt消息上下文
     * @param clientId 客户端唯一Id
     * @param username 客户端登录名
     */
    @Async
    public void online(ChannelContext context, String clientId, String username) {
        log.info("online :context => {}" , context);
        log.info("online :clientId => {}" , clientId);
        log.info("online :username => {}" , username);
        CovertType covertType = covert.checkMqttClient(clientId);
        if (covertType == null) {
            log.error("异常的消息接收clientId => {}", clientId);
            return;
        }
        covertType.online(context, clientId, username);
    }

    /**
     * Mqtt下线处理
     * @param context Mqtt消息上下文
     * @param clientId 客户端唯一Id
     * @param username 客户端登录名
     * @param reason 离线遗嘱消息
     */
    @Async
    public void offline(ChannelContext context, String clientId, String username, String reason) {
        log.info("offline :context => {}" , context);
        log.info("offline :clientId => {}" , clientId);
        log.info("offline :username => {}" , username);
        log.info("offline :reason => {}" , reason);
        CovertType covertType = covert.checkMqttClient(clientId);
        if (covertType == null) {
            log.error("异常的消息接收clientId => {}", clientId);
            return;
        }
        covertType.offline(context, clientId, username, reason);
    }

    @Async
    public void onSubscribed(ChannelContext context, String clientId, String topicFilter, int qos) {
        CovertType covertType = covert.checkMqttClient(clientId);
        if (covertType == null) {
            log.error("异常的消息接收 clientId => {}", clientId);
            return;
        }
        covertType.onSubscribed(context, clientId, topicFilter, qos);
    }

    @Async
    public void onUnsubscribed(ChannelContext context, String clientId, String topicFilter) {
        CovertType covertType = covert.checkMqttClient(clientId);
        if (covertType == null) {
            log.error("异常的消息接收clientId => {}", clientId);
            return;
        }
        covertType.onUnsubscribed(context, clientId, topicFilter);
    }


    public boolean checkCanPublish(String clientId, String topic, int value, boolean isRetain) {
        CovertType covertType = covert.checkMqttClient(clientId);
        if (covertType == null) {
            log.error("异常的消息接收clientId => {}", clientId);
            return false;
        }
        return covertType.checkCanPublish(clientId, topic, value, isRetain);
    }

    /**
     * 检查Mqtt客户端来源
     * @param clientId 客户端唯一Id
     * @return CovertType 来源类型
     */
    private CovertType checkMqttClient(String clientId) {
        return covert.checkMqttClient(clientId, "covert", "covert");
    }

    /**
     * 检查Mqtt客户端来源
     * @param clientId 客户端唯一Id
     * @param userName 客户端登录名
     * @param password 客户端登录密码
     * @return CovertType 来源类型
     */
    private CovertType checkMqttClient(String clientId, String userName, String password) {
        // 验证账号密码是否为空
        if (StrUtils.isBlank(clientId) || StrUtils.isBlank(userName) || StrUtils.isBlank(password)) {
            return null;
        }
        if (StrUtils.startWith(clientId, covert.memberCovert.getTag())) {
            return covert.memberCovert;
        }
        return null;
    }


}
